#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('./express.js');
var debug = require('debug')('service:server');
var http = require('http');
var moment = require('moment');
const fs = require('fs');
const path = require('path');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort('7000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.Server(app);

const websocket = require('socket.io')(server);

// --------------- websocket code start ----------------------------

// Mapping objects to easily map sockets and users.
var clients = {};
var users = {};
var userIdMap = {};
let currentUserCount = 0;

// 连接 websocket
websocket.on('connection', (socket) => {
  clients[socket.id] = socket;
  currentUserCount++;
  // 接收到用户 ID
  socket.on('userJoined', (obj={}, fn) => {
    const  userId = socket.id;
    if (obj &&  users[obj.username]===undefined) {
      const params = {
        userId: obj.userId || socket.id,
        username: obj.username,
      };
      if(userIdMap[userId]!==undefined){
        users[userIdMap[userId].username] = undefined;
      }
      users[obj.username] = params;
      userIdMap[userId] = params;
      websocket.emit('login',{onlineUser: users,onlineCount:currentUserCount,user:users[obj.username]});
      console.log(`userId:${obj.username}`);
      fn({
        userId,
        result: 'success',
      });
    } else {
      fn({
        result: 'fail',
        msg: '用户已存在',
      });
    }

  });
  // 接收消息
  socket.on('message', (message, func)=> {
    console.log('接收到消息', JSON.stringify(message));
    // const basePath = path.join(__dirname, new Date().getTime()+'.jpg');
    // let dataBuffer = new Buffer(message.data, 'ascii');
    // fs.appendFile(basePath, dataBuffer);
    websocket.emit('message', message);
    func('success');
  });

  // 接收消息
  socket.on('file', (file, func)=> {
    console.log('接收到文件');
    const fileName = path.join('/file',new Date().getTime()+path.extname(file.path));
    const basePath = path.join(__dirname, '..', 'public', fileName);
    let dataBuffer = Buffer.concat(file.data.map((item)=> {
      return Buffer.from(item, 'ascii');
    }));
    fs.appendFile(basePath, dataBuffer, function (err) {
      if(err){
        console.error('文件接收失败', error);
      }else{
        if(file.mime.startsWith('image')){
          file.message.image = fileName;
        }else{
          file.message.video = fileName;
        }
        console.log('文件保存成功');
        websocket.emit('message', [file.message]);
        func(fileName);
      }
    });
  });

  // 客户端断开链接
  socket.on('disconnect', ()=> {
    if(!userIdMap[socket.id]){
      return;
    }
    const username = userIdMap[socket.id].username;
    console.log(`有用户退出聊天室:${username}`);
    currentUserCount--;
    websocket.emit('logout',{onlineUser: users,onlineCount:currentUserCount,user:userIdMap[socket.id]});
    userIdMap[socket.id] = undefined;
    users[username] = undefined;
  });
});

// Allow the server to participate in the chatroom through stdin.
var stdin = process.openStdin();
stdin.addListener('data', function (d) {
  // _sendAndSaveMessage({
  //   text: d.toString().trim(),
  //   createdAt: new Date(),
  //   user: { _id: 'robot' }
  // }, null /* no socket */, true /* send from server */);
});
// --------------- websocket code end ----------------------------

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
  console.log(`服务启动成功:${port}`);
}
